স্প্রিং বুট ক্লায়েন্ট (Spring Boot Client) তৈরি করার জন্য কিছু Best Practices অনুসরণ করা গুরুত্বপূর্ণ। এগুলি স্প্রিং বুট অ্যাপ্লিকেশনের কার্যকারিতা, নিরাপত্তা, রক্ষণাবেক্ষণযোগ্যতা এবং স্কেলেবিলিটি উন্নত করতে সাহায্য করবে। নিচে Spring Boot Client এর জন্য সেরা কিছু পদ্ধতি এবং কৌশল আলোচনা করা হলো।
RestTemplate
এবং WebClient
ব্যবহারRestTemplate ব্যবহারকারী অ্যাপ্লিকেশন এবং API সার্ভিসের মধ্যে সিঙ্ক্রোনাস (synchronous) যোগাযোগের জন্য কার্যকর, তবে নতুন প্রোজেক্টে WebClient ব্যবহার করা বেশি উপযোগী, কারণ এটি asynchronous এবং reactive প্রোগ্রামিং সমর্থন করে।
Best Practice:
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class ApiClient {
private final WebClient webClient;
public ApiClient(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
public Mono<String> fetchPost(int postId) {
return webClient.get()
.uri("/posts/{id}", postId)
.retrieve()
.bodyToMono(String.class);
}
}
API কলের জন্য Error Handling অপরিহার্য। ক্লায়েন্ট-সাইডে একাধিক ত্রুটি ঘটতে পারে, যেমন timeout
, connection error
, অথবা server error
। এগুলি Resilience4j এর মতো লাইব্রেরি ব্যবহার করে সঠিকভাবে পরিচালনা করা উচিত।
Best Practice:
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;
@Service
public class ResilientApiClient {
private final WebClient webClient;
public ResilientApiClient(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
@CircuitBreaker(name = "myService", fallbackMethod = "fallbackFetchPost")
public String fetchPost(int postId) {
return webClient.get()
.uri("/posts/{id}", postId)
.retrieve()
.bodyToMono(String.class)
.block();
}
public String fallbackFetchPost(int postId, Throwable t) {
return "Fallback response for post " + postId;
}
}
WebClient এর মাধ্যমে asynchronous API কলগুলি ব্যবহার করা blocking সার্ভিস কলগুলির তুলনায় অনেক বেশি কার্যকর এবং দ্রুত।
Best Practice:
public Mono<String> fetchPostAsync(int postId) {
return webClient.get()
.uri("/posts/{id}", postId)
.retrieve()
.bodyToMono(String.class);
}
Mono এবং Flux ব্যবহার করে ডেটা রিটার্ন করা যায়, যা reactive programming-এর সুবিধা নিয়ে আসে।
Connection pooling সার্ভারের সাথে একাধিক কনেকশন তৈরি করতে সহায়ক এবং timeout কনফিগারেশন সংস্থাপন করা খুবই গুরুত্বপূর্ণ। এটি সার্ভিস কলের জন্য দ্রুত সাড়া নিশ্চিত করে।
Best Practice:
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
manager.setMaxTotal(50); // Max Total Connections
manager.setDefaultMaxPerRoute(20); // Max Connections per Route
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(manager)
.build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
factory.setConnectTimeout(5000); // Connection Timeout
factory.setReadTimeout(5000); // Read Timeout
return new RestTemplate(factory);
}
}
সঠিকভাবে লগিং এবং মনিটরিং করা গুরুত্বপূর্ণ। এটি কোডের সমস্যা চিহ্নিত করতে এবং পারফরম্যান্স ট্র্যাক করতে সহায়ক।
Best Practice:
management.endpoints.web.exposure.include=health,metrics,info
Endpoint: http://localhost:8080/actuator/metrics
- অ্যাপ্লিকেশনের মেট্রিক্স মনিটর করতে।
যখন আপনি একটি ক্লায়েন্ট তৈরি করেন, তখন নিরাপত্তা নিশ্চিত করা অত্যন্ত গুরুত্বপূর্ণ। OAuth2 বা JWT (JSON Web Token) ব্যবহার করে API কলগুলির জন্য সুরক্ষা যোগ করা উচিত।
Best Practice:
@RestController
public class SecureApiController {
private final WebClient webClient;
public SecureApiController(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder
.baseUrl("https://secured-api.com")
.build();
}
@GetMapping("/secure-data")
public Mono<String> fetchSecureData() {
return webClient.get()
.uri("/data")
.attributes(clientRegistrationId("my-client"))
.retrieve()
.bodyToMono(String.class);
}
}
API-এর ভিন্ন সংস্করণে কর্মক্ষমতা নিশ্চিত করতে API versioning ব্যবহার করুন এবং প্রতিটি গুরুত্বপূর্ণ অংশের জন্য ডকুমেন্টেশন তৈরি করুন।
Best Practice:
Unit testing এবং Integration testing ক্লায়েন্ট কোডের জন্য অত্যন্ত গুরুত্বপূর্ণ।
Best Practice:
স্প্রিং বুট ক্লায়েন্ট তৈরি করার সময়, উপরোক্ত best practices অনুসরণ করলে আপনার অ্যাপ্লিকেশন দ্রুত, নিরাপদ এবং রক্ষণাবেক্ষণযোগ্য হবে। এই প্রাকটিসগুলো কার্যকরী এবং স্কেলেবিলিটির দিক থেকে গুরুত্বপূর্ণ এবং তা API কলের ক্ষেত্রে দক্ষতা বৃদ্ধি করতে সহায়ক।
এটা গুরুত্বপূর্ণ যে আপনি স্প্রিং বুট ক্লায়েন্টের মাধ্যমে API কল ডিজাইন এবং রিকোয়েস্ট হ্যান্ডলিং এর জন্য কিছু সেরা অভ্যাস অনুসরণ করুন যাতে আপনার অ্যাপ্লিকেশনটি নিরাপদ, দক্ষ এবং স্কেলেবল হয়। নীচে কিছু Best Practices দেয়া হল যা API কল ডিজাইন এবং রিকোয়েস্ট হ্যান্ডলিং এর ক্ষেত্রে সাহায্য করবে:
একটি API ক্লায়েন্ট অ্যাপ্লিকেশন তৈরির সময় Exception Handling খুবই গুরুত্বপূর্ণ। যখন আপনি API কল করেন, তখন ত্রুটির সম্ভাবনা থাকে (যেমন নেটওয়ার্ক সমস্যা, সার্ভার সমস্যা ইত্যাদি) এবং সেগুলোর যথাযথ হ্যান্ডলিং প্রয়োজন।
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
public class CustomRestTemplate {
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new CustomResponseErrorHandler());
return restTemplate;
}
public static class CustomResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return response.getStatusCode().isError();
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// Log error or throw custom exception
System.out.println("Error: " + response.getStatusCode());
}
}
}
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
public class ApiService {
private final WebClient webClient;
public ApiService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("http://example.com").build();
}
public String getData(String endpoint) {
return webClient.get()
.uri(endpoint)
.retrieve()
.onStatus(status -> status.is4xxClientError() || status.is5xxServerError(), response -> {
throw new WebClientResponseException("API Call Failed", response.statusCode().value(),
response.statusCode().getReasonPhrase(), response.headers().asHttpHeaders(), null, null);
})
.bodyToMono(String.class)
.block();
}
}
API সার্ভিসের সঙ্গে যোগাযোগের সময় যদি অস্থায়ী ত্রুটি হয়, তবে পুনরায় চেষ্টা করার জন্য Retry Logic ব্যবহার করুন। এটি সার্ভারের চাপ কমাতে সহায়ক হতে পারে এবং সার্ভিস অ্যাভেইলেবিলিটি বাড়াতে পারে।
resilience4j:
retry:
configs:
default:
maxAttempts: 3
waitDuration: 2s
instances:
apiService:
maxAttempts: 5
waitDuration: 1s
import io.github.resilience4j.retry.annotation.Retry;
import org.springframework.stereotype.Service;
@Service
public class ApiService {
@Retry(name = "apiService", fallbackMethod = "fallbackMethod")
public String getData(String endpoint) {
// Simulate API call
return "API Data";
}
public String fallbackMethod(Throwable throwable) {
return "Fallback Response";
}
}
WebClient ব্যবহার করে non-blocking API কল করা যেতে পারে, যা অ্যাপ্লিকেশনটির পারফরম্যান্স বৃদ্ধি করতে সাহায্য করে।
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class ApiService {
private final WebClient webClient;
public ApiService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("http://example.com").build();
}
public Mono<String> getDataAsync(String endpoint) {
return webClient.get()
.uri(endpoint)
.retrieve()
.bodyToMono(String.class);
}
}
Asynchronous API কল ব্যবহার করে সিস্টেমে আই/ও অপারেশনের জন্য ব্লকিং কমানো যায় এবং পারফরম্যান্স উন্নত হয়।
API রিকোয়েস্টের সময় উপযুক্ত টাইমআউট কনফিগার করা গুরুত্বপূর্ণ, যাতে সার্ভার অনুপস্থিত থাকলে আপনার অ্যাপ্লিকেশন ব্লক না হয়।
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
public class ApiService {
public RestTemplate restTemplate() {
// Set timeout configuration
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000) // Connection timeout in ms
.setSocketTimeout(5000) // Socket timeout in ms
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
}
API এর প্রতি নির্দিষ্ট সময়ে সর্বোচ্চ রিকোয়েস্ট সংখ্যা নির্ধারণ করে Rate Limiting নিশ্চিত করা যায়। এটি API কলের ওভারলোড বা ডিনায়াল অব সার্ভিস (DoS) আক্রমণ রোধ করতে সাহায্য করে।
resilience4j:
rate-limiter:
configs:
default:
limitForPeriod: 5
limitRefreshPeriod: 1s
timeoutDuration: 500ms
instances:
apiService:
limitForPeriod: 10
limitRefreshPeriod: 1s
API কল করার সময় Authentication এবং Authorization ব্যবস্থার সাথে সঠিকভাবে কাজ করা খুবই গুরুত্বপূর্ণ। OAuth2, JWT, বা Basic Authentication ব্যবহার করা যেতে পারে।
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.context.annotation.Bean;
public class ApiService {
@Bean
public OAuth2RestTemplate oAuth2RestTemplate(ClientRegistration clientRegistration) {
return new OAuth2RestTemplate(clientRegistration);
}
public String getData(String url) {
OAuth2RestTemplate restTemplate = oAuth2RestTemplate(null);
return restTemplate.getForObject(url, String.class);
}
}
প্রত্যেকটি API রিকোয়েস্ট এবং রেসপন্স লগিং করা গুরুত্বপূর্ণ। এটি ডিবাগিং এবং পারফরম্যান্স মনিটরিংয়ের জন্য সহায়ক।
স্প্রিং অ্যাকচুয়েটরের মাধ্যমে অ্যাপ্লিকেশনের স্টেটাস এবং হেলথ চেক মনিটর করতে পারেন।
management:
endpoints:
web:
exposure:
include: health, metrics, info
Health Checks API এবং Metrics মনিটরিং আপনাকে সার্ভিসের স্টেটাস এবং রিসোর্স ব্যবহার দেখতে সাহায্য করবে।
API ভার্সনিংয়ের মাধ্যমে, আপনি পুরানো ক্লায়েন্টদের প্রভাবিত না করেই নতুন ফিচার যুক্ত করতে পারবেন। আপনি URL, হেডার, বা প্যারামিটার দ্বারা ভার্সনিং পরিচালনা করতে পারেন।
@GetMapping("/api/v1/resource")
public String getResourceV1() {
return "API Version 1";
}
@GetMapping("/api/v2/resource")
public String getResourceV2() {
return "API Version 2";
}
API রিকোয়েস্ট এবং রেসপন্স এর জন্য DTOs (Data Transfer Objects) ব্যবহার করা উচিত, যাতে ডাটা সঠিকভাবে ফরম্যাট করা হয় এবং সহজে ডিবাগ করা যায়।
public class UserDTO {
private String name;
private int age;
// Getters and Setters
}
API কলের সময় HTTPS ব্যবহার করা অত্যন্ত গুরুত্বপূর্ণ। এছাড়া Input Validation, SQL Injection Prevention, Cross-Site Scripting (XSS) প্রোটেকশনসহ অন্যান্য নিরাপত্তা পদ্ধতি ব্যবহার করা উচিত।
স্প্রিং বুট ক্লায়েন্টের মাধ্যমে API কল ডিজাইন এবং রিকোয়েস্ট হ্যান্ডলিংয়ের জন্য উপরের Best Practices অনুসরণ করলে অ্যাপ্লিকেশনটির পারফরম্যান্স, সিকিউরিটি এবং স্কেলেবিলিটি উন্নত হবে। এগুলি API ডেভেলপমেন্টের জন্য টেকসই এবং রিলায়েবল পদ্ধতি প্রদান করবে।
Spring Boot ক্লায়েন্ট তৈরি করার সময় Security, Error Handling, এবং Performance Optimization-এর দিকে মনোযোগ দেওয়া অত্যন্ত গুরুত্বপূর্ণ। নিচে প্রতিটি বিষয় নিয়ে কিছু টিপস দেওয়া হলো:
# Enable SSL in Spring Boot application.properties
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=your-password
server.ssl.keyStoreType=JKS
server.ssl.keyAlias=selfsigned
RestTemplate
বা WebClient
এর মাধ্যমে অ্যাক্সেস টোকেন সংগ্রহ করে ব্যবহার করুন।// Example: OAuth2 Token retrieval via RestTemplate
String accessToken = "your-access-token";
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
HttpEntity<String> entity = new HttpEntity<>(headers);
# Use environment variables for storing API keys
api.key=${API_KEY}
// Disabling CSRF for Rest API (if needed)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // Only disable CSRF for REST APIs if absolutely necessary
}
}
@ControllerAdvice
@ControllerAdvice
ব্যবহার করে একটি সাধারণ Exception Handler তৈরি করুন যাতে সব ধরনের এক্সসেপশন এক জায়গায় হ্যান্ডল করা যায়।@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleAllExceptions(Exception ex) {
ErrorResponse errorResponse = new ErrorResponse("ERROR", ex.getMessage());
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
404 Not Found
, 400 Bad Request
ইত্যাদি হ্যান্ডল করুন।@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Object> handleResourceNotFound(ResourceNotFoundException ex) {
ErrorResponse errorResponse = new ErrorResponse("NOT_FOUND", ex.getMessage());
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
RestTemplate
and WebClient
Error HandlingRestTemplate
এবং WebClient
-এ কাস্টম Error Handler সেটআপ করুন।RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// Custom error handling logic
}
});
webClient.get()
.uri("/data")
.retrieve()
.onStatus(HttpStatus::is4xxClientError, response -> {
// Handle 4xx client errors
return Mono.error(new RuntimeException("Client Error"));
})
.onStatus(HttpStatus::is5xxServerError, response -> {
// Handle 5xx server errors
return Mono.error(new RuntimeException("Server Error"));
})
.bodyToMono(String.class);
public class ErrorResponse {
private String errorCode;
private String errorMessage;
// getters and setters
}
@Bean
public RestTemplate restTemplate() {
HttpClient httpClient = HttpClients.custom()
.setMaxConnTotal(200)
.setMaxConnPerRoute(20)
.build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
@Bean
public WebClient.Builder webClientBuilder(ReactiveClientHttpConnector connector) {
return WebClient.builder().clientConnector(connector);
}
@Bean
public ReactiveClientHttpConnector connector() {
return new ReactorClientHttpConnector(HttpClient.create()
.tcpConfiguration(tcpClient -> tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000))
.wiretap(true));
}
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("responses");
}
@Cacheable("responses")
public String fetchDataFromServer() {
// Make HTTP request
}
@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000); // 5 seconds
factory.setReadTimeout(5000); // 5 seconds
return new RestTemplate(factory);
}
@Bean
public WebClient.Builder webClientBuilder() {
return WebClient.builder()
.baseUrl("https://api.example.com")
.clientConnector(new ReactorClientHttpConnector(HttpClient.create().responseTimeout(Duration.ofSeconds(5))));
}
Mono<String> result = webClient.get()
.uri("/data")
.retrieve()
.bodyToMono(String.class);
result.subscribe(response -> System.out.println(response));
এই টিপসগুলো অনুসরণ করলে আপনার Spring Boot ক্লায়েন্টের নিরাপত্তা, কার্যকারিতা এবং পারফরম্যান্স উন্নত হবে।
Spring Boot Client তৈরি করার সময় কিছু best practices অনুসরণ করা ভালো, যা কোডের মান, কর্মক্ষমতা এবং নিরাপত্তা বৃদ্ধি করতে সহায়তা করে। নিচে Spring Boot Client ডেভেলপ করার সময় কিছু সাধারণ best practices এবং উদাহরণ দেওয়া হয়েছে।
WebClient হল Spring WebFlux এর অংশ, যা নন-ব্লকিং এবং রিয়্যাক্টিভ অপারেশন সমর্থন করে, যেখানে RestTemplate ব্লকিং I/O অপারেশন হ্যান্ডল করে। আপনি যদি অ্যাসিনক্রোনাস এবং রিয়্যাক্টিভ অ্যাপ্লিকেশন তৈরি করেন, তাহলে WebClient ব্যবহার করা উচিৎ।
Best Practice:
@Autowired
বা @Bean
দিয়ে ইনস্ট্যান্স তৈরি করুন, এবং যথাযথ Exception Handling প্রয়োগ করুন।API কল গুলি Service Layer এ রাখা উচিত, এবং Controller Layer শুধু HTTP রিকোয়েস্ট হ্যান্ডল করবে। এর ফলে কোড পুনরায় ব্যবহারযোগ্য হয় এবং টেস্টিং সহজ হয়।
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class ApiService {
private final WebClient webClient;
@Autowired
public ApiService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
public String fetchPosts() {
return webClient.get()
.uri("/posts")
.retrieve()
.bodyToMono(String.class)
.block(); // block() can be avoided in a real async use case
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ApiController {
private final ApiService apiService;
@Autowired
public ApiController(ApiService apiService) {
this.apiService = apiService;
}
@GetMapping("/posts")
public String getPosts() {
return apiService.fetchPosts();
}
}
API কলের রেসপন্স সঠিকভাবে হ্যান্ডল করা জরুরি, বিশেষ করে যখন ত্রুটি বা অপ্রত্যাশিত ডেটা আসে। ResponseEntity
ব্যবহার করে কাস্টম HTTP স্ট্যাটাস কোড সহ রেসপন্স প্রদান করা উচিত।
Best Practice:
try-catch
ব্লক ব্যবহার করুন এবং ResponseEntity
দিয়ে কাস্টম HTTP স্ট্যাটাস কোড দিন।import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
@Service
public class ApiService {
private final WebClient webClient;
public ApiService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
public ResponseEntity<String> fetchPosts() {
try {
String response = webClient.get()
.uri("/posts")
.retrieve()
.bodyToMono(String.class)
.block();
return ResponseEntity.ok(response);
} catch (WebClientResponseException e) {
return ResponseEntity.status(e.getStatusCode()).body("Error: " + e.getMessage());
}
}
}
যখন আপনি দীর্ঘ সময় ধরে চলা বা I/O-বাউন্ড অপারেশন (যেমন API কল) করছেন, তখন অ্যাসিনক্রোনাস অপারেশন ব্যবহার করা উচিত যাতে এটি থ্রেড ব্লক না করে। WebClient এবং Mono/Flux ব্যবহার করে আপনি অ্যাসিনক্রোনাস অপারেশন হ্যান্ডল করতে পারেন।
Best Practice:
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class ApiService {
private final WebClient webClient;
public ApiService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
public Mono<String> fetchPostsAsync() {
return webClient.get()
.uri("/posts")
.retrieve()
.bodyToMono(String.class);
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
public class ApiController {
private final ApiService apiService;
@Autowired
public ApiController(ApiService apiService) {
this.apiService = apiService;
}
@GetMapping("/posts")
public Mono<String> getPosts() {
return apiService.fetchPostsAsync();
}
}
API কলের জন্য টাইমআউট এবং রিট্রাই লজিক ব্যবহার করা গুরুত্বপূর্ণ, বিশেষ করে যখন আপনার অ্যাপ্লিকেশন বাইরের সার্ভিসের উপর নির্ভরশীল থাকে। আপনি WebClient-এ timeout
এবং retry
লজিক যোগ করতে পারেন।
Best Practice:
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
import java.time.Duration;
@Service
public class ApiService {
private final WebClient webClient;
public ApiService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com")
.build();
}
public Mono<String> fetchPostsWithRetry() {
return webClient.get()
.uri("/posts")
.retrieve()
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(5)) // Timeout after 5 seconds
.retryWhen(Retry.fixedDelay(3, Duration.ofSeconds(2))) // Retry up to 3 times with 2 seconds delay
.onErrorReturn("Error fetching data");
}
}
বহু API কলের জন্য একই রেসপন্স আসতে পারে, যেমন ব্যবহারকারীর তথ্য। এ ধরনের ডেটা কিভাবে ক্যাশে করা যায় তা নিশ্চিত করা উচিত, যাতে সিস্টেমের কার্যক্ষমতা বাড়ানো যায়।
Best Practice:
API কল নিরাপদ করতে OAuth2 বা Basic Authentication ব্যবহার করা উচিত। যখন নিরাপত্তা গুরুত্বপূর্ণ, তখন API কলের জন্য Bearer token বা Basic Auth ব্যবহার করতে হবে।
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.http.HttpHeaders;
@Service
public class ApiService {
private final WebClient webClient;
public ApiService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com")
.defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer YOUR_TOKEN")
.build();
}
public String fetchPostsWithAuth() {
return webClient.get()
.uri("/posts")
.retrieve()
.bodyToMono(String.class)
.block();
}
}
Spring Boot Client তৈরি করার সময় best practices অনুসরণ করলে কোড আরো মেনটেইনেবল, সিকিউর এবং স্কেলেবল হয়ে ওঠে। সঠিকভাবে WebClient বা RestTemplate ব্যবহার, Error Handling, Async Operations, Retry Logic, Timeout Configuration এবং Security এই সবই গুরুত্বপূর্ণ।
যদি আরো কোনো কনফিগারেশন বা কোড উদাহরণ দরকার হয়, জানাবেন! 😊
Read more